#!/usr/bin/env tsx

import { existsSync, readFileSync } from 'fs';
import { join } from 'path';

interface CheckResult {
  name: string;
  status: 'pass' | 'fail' | 'warning';
  message: string;
}

class PrePublishChecker {
  private results: CheckResult[] = [];

  private addResult(name: string, status: 'pass' | 'fail' | 'warning', message: string) {
    this.results.push({ name, status, message });
  }

  private checkFileExists(filePath: string, description: string): boolean {
    if (existsSync(filePath)) {
      this.addResult(`File: ${description}`, 'pass', `✅ ${filePath} exists`);
      return true;
    } else {
      this.addResult(`File: ${description}`, 'fail', `❌ ${filePath} missing`);
      return false;
    }
  }

  private checkPackageJson() {
    console.log('\n📦 Checking package.json...');
    
    if (!this.checkFileExists('package.json', 'Package configuration')) {
      return;
    }

    try {
      const pkg = JSON.parse(readFileSync('package.json', 'utf-8'));
      
      // Check required fields
      const requiredFields = ['name', 'version', 'description', 'main', 'types', 'author', 'license'];
      for (const field of requiredFields) {
        if (pkg[field]) {
          this.addResult(`Package: ${field}`, 'pass', `✅ ${field}: ${pkg[field]}`);
        } else {
          this.addResult(`Package: ${field}`, 'fail', `❌ Missing ${field}`);
        }
      }

      // Check scoped package name
      if (pkg.name && pkg.name.startsWith('@')) {
        this.addResult('Package: Scoped name', 'pass', `✅ Scoped package: ${pkg.name}`);
      } else {
        this.addResult('Package: Scoped name', 'warning', `⚠️ Not a scoped package`);
      }

      // Check publishConfig
      if (pkg.publishConfig && pkg.publishConfig.access === 'public') {
        this.addResult('Package: Publish config', 'pass', `✅ Public access configured`);
      } else {
        this.addResult('Package: Publish config', 'warning', `⚠️ No public access config`);
      }

      // Check files array
      if (pkg.files && pkg.files.length > 0) {
        this.addResult('Package: Files', 'pass', `✅ Files specified: ${pkg.files.join(', ')}`);
      } else {
        this.addResult('Package: Files', 'warning', `⚠️ No files array specified`);
      }

      // Check scripts
      const importantScripts = ['build', 'test', 'prepublishOnly'];
      for (const script of importantScripts) {
        if (pkg.scripts && pkg.scripts[script]) {
          this.addResult(`Script: ${script}`, 'pass', `✅ ${script} script exists`);
        } else {
          this.addResult(`Script: ${script}`, 'warning', `⚠️ No ${script} script`);
        }
      }

    } catch (error) {
      this.addResult('Package: Parse', 'fail', `❌ Failed to parse package.json: ${error}`);
    }
  }

  private checkBuildOutput() {
    console.log('\n🏗️ Checking build output...');
    
    if (!this.checkFileExists('dist', 'Build directory')) {
      return;
    }

    // Check main entry points
    const entryPoints = [
      'dist/index.js',
      'dist/index.d.ts',
      'dist/client.js',
      'dist/client.d.ts'
    ];

    for (const entry of entryPoints) {
      this.checkFileExists(entry, `Entry point: ${entry}`);
    }

    // Check core modules
    const coreModules = [
      'dist/core/config.js',
      'dist/core/connection-pool.js',
      'dist/core/producer.js',
      'dist/core/consumer.js',
      'dist/core/message.js'
    ];

    for (const module of coreModules) {
      this.checkFileExists(module, `Core module: ${module}`);
    }
  }

  private checkDocumentation() {
    console.log('\n📚 Checking documentation...');
    
    this.checkFileExists('README.md', 'README file');
    this.checkFileExists('LICENSE', 'License file');
    
    // Check README content
    if (existsSync('README.md')) {
      const readme = readFileSync('README.md', 'utf-8');
      
      if (readme.includes('# @roasmax/rabbitmq')) {
        this.addResult('README: Title', 'pass', '✅ Package title found');
      } else {
        this.addResult('README: Title', 'warning', '⚠️ Package title not found');
      }

      if (readme.includes('## Installation')) {
        this.addResult('README: Installation', 'pass', '✅ Installation section found');
      } else {
        this.addResult('README: Installation', 'warning', '⚠️ Installation section missing');
      }

      if (readme.includes('```typescript') || readme.includes('```ts')) {
        this.addResult('README: Examples', 'pass', '✅ TypeScript examples found');
      } else {
        this.addResult('README: Examples', 'warning', '⚠️ No TypeScript examples');
      }
    }
  }

  private checkGitStatus() {
    console.log('\n🔄 Checking git status...');
    
    if (existsSync('.git')) {
      this.addResult('Git: Repository', 'pass', '✅ Git repository initialized');
    } else {
      this.addResult('Git: Repository', 'warning', '⚠️ No git repository');
    }
  }

  private checkNpmAuth() {
    console.log('\n🔐 Checking npm authentication...');
    
    // This would require running npm whoami, but we'll just note it
    this.addResult('NPM: Auth', 'warning', '⚠️ Please ensure you are logged in to npm');
  }

  public async runAllChecks(): Promise<boolean> {
    console.log('🚀 Running pre-publish checks for @roasmax/rabbitmq...\n');

    this.checkPackageJson();
    this.checkBuildOutput();
    this.checkDocumentation();
    this.checkGitStatus();
    this.checkNpmAuth();

    // Print results
    console.log('\n📊 Check Results:');
    console.log('==================');

    let hasFailures = false;
    let hasWarnings = false;

    for (const result of this.results) {
      const icon = result.status === 'pass' ? '✅' : result.status === 'fail' ? '❌' : '⚠️';
      console.log(`${icon} ${result.name}: ${result.message}`);
      
      if (result.status === 'fail') hasFailures = true;
      if (result.status === 'warning') hasWarnings = true;
    }

    console.log('\n📈 Summary:');
    console.log(`✅ Passed: ${this.results.filter(r => r.status === 'pass').length}`);
    console.log(`⚠️ Warnings: ${this.results.filter(r => r.status === 'warning').length}`);
    console.log(`❌ Failed: ${this.results.filter(r => r.status === 'fail').length}`);

    if (hasFailures) {
      console.log('\n❌ Pre-publish checks failed! Please fix the issues above.');
      return false;
    } else if (hasWarnings) {
      console.log('\n⚠️ Pre-publish checks passed with warnings. Review the warnings above.');
      return true;
    } else {
      console.log('\n🎉 All pre-publish checks passed! Ready to publish.');
      return true;
    }
  }
}

// Run the checks
const checker = new PrePublishChecker();
checker.runAllChecks().then(success => {
  process.exit(success ? 0 : 1);
}).catch(error => {
  console.error('❌ Error running pre-publish checks:', error);
  process.exit(1);
});
